package com.zb.orm.query;

import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.Set;

import com.zb.orm.query.operator.BETWEEN;
import com.zb.orm.query.operator.EQ;
import com.zb.orm.query.operator.GE;
import com.zb.orm.query.operator.GT;
import com.zb.orm.query.operator.IN;
import com.zb.orm.query.operator.LE;
import com.zb.orm.query.operator.LIKE;
import com.zb.orm.query.operator.LT;
import com.zb.orm.query.operator.NOT_BETWEEN;
import com.zb.orm.query.operator.NOT_EQ;
import com.zb.orm.query.operator.NOT_IN;
import com.zb.orm.query.operator.NOT_NULL;
import com.zb.orm.query.operator.NULL;
import com.zb.orm.query.operator.Operator;

/**
 * 查询上下文，用于拼接多个查询条件
 * 
 * 作者: zhoubang 日期：2015年3月26日 下午1:25:28
 */
public class QueryContext implements Iterable<QueryContextPiece> {

    private Set<QueryContextPiece> pieces = new LinkedHashSet<QueryContextPiece>();

    /**
     * <p>
     * clear.
     * </p>
     */
    public QueryContext clear() {
        this.pieces.clear();
        return this;
    }

    /**
     * and拼接
     * 
     * @param field
     * @param value
     * @return
     */
    public QueryContext andEquals(final String field, final Object value) {
        return this.and(field, Operator.eq, value);
    }

    /**
     * or拼接
     * 
     * @param field
     * @param value
     * @return
     */
    public QueryContext orEquals(final String field, final Object value) {
        return this.or(field, Operator.eq, value);
    }

    /**
     * 
     * @param piece
     */
    private void add(QueryContextPiece piece) {
        this.pieces.add(piece);
    }

    /**
     * 等于参数拼接
     * 
     * @param field
     * @param operator
     * @param value
     * @return
     */
    public QueryContext and(final String field, EQ operator, final Object value) {
        this.add(QueryContextPiece.and(field, operator, value));
        return this;
    }

    /**
     * 不等于参数拼接
     * 
     * @param field
     * @param operator
     * @param value
     * @return
     */
    public QueryContext and(final String field, NOT_EQ operator, final Object value) {
        this.add(QueryContextPiece.and(field, operator, value));
        return this;
    }

    /**
     * 小于参数拼接
     * 
     * @param field
     * @param operator
     * @param value
     * @return
     */
    public QueryContext and(final String field, LT operator, final Object value) {
        this.add(QueryContextPiece.and(field, operator, value));
        return this;
    }

    /**
     * 大于参数拼接
     * 
     * @param field
     * @param operator
     * @param value
     * @return
     */
    public QueryContext and(final String field, GT operator, final Object value) {
        this.add(QueryContextPiece.and(field, operator, value));
        return this;
    }

    /**
     * 小于等于
     * 
     * @param field
     * @param operator
     * @param value
     * @return
     */
    public QueryContext and(final String field, LE operator, final Object value) {
        this.add(QueryContextPiece.and(field, operator, value));
        return this;
    }

    /**
     * 大于等于
     * 
     * @param field
     * @param operator
     * @param value
     * @return
     */
    public QueryContext and(final String field, GE operator, final Object value) {
        this.add(QueryContextPiece.and(field, operator, value));
        return this;
    }

    /**
     * 是否空
     * 
     * @param field
     * @param operator
     * @return
     */
    public QueryContext and(final String field, NULL operator) {
        this.add(QueryContextPiece.and(field, operator));
        return this;
    }

    /**
     * 是否非空
     * 
     * @param field
     * @param operator
     * @return
     */
    public QueryContext and(final String field, NOT_NULL operator) {
        this.add(QueryContextPiece.and(field, operator));
        return this;
    }

    /**
     * 模糊查询
     * 
     * @param field
     * @param operator
     * @param value
     * @return
     */
    public QueryContext and(final String field, LIKE operator, final Object value) {
        this.add(QueryContextPiece.and(field, operator, value));
        return this;
    }

    /**
     * 包含
     * 
     * @param field
     * @param operator
     * @param value
     * @return
     */
    @SuppressWarnings("unchecked")
    public <Z extends Object> QueryContext and(final String field, IN operator, final Z... value) {
        this.add(QueryContextPiece.and(field, operator, value));
        return this;
    }

    /**
     * 不包含
     * 
     * @param field
     * @param operator
     * @param value
     * @return
     */
    @SuppressWarnings("unchecked")
    public <Z extends Object> QueryContext and(final String field, NOT_IN operator, final Z... value) {
        this.add(QueryContextPiece.and(field, operator, value));
        return this;
    }

    /**
     * 介于两者之间
     * 
     * @param field
     * @param operator
     * @param value1
     * @param value2
     * @return
     */
    public QueryContext and(final String field, BETWEEN operator, final Object value1, final Object value2) {
        this.add(QueryContextPiece.and(field, operator, value1, value2));
        return this;
    }

    /**
     * 介于两者之外
     * 
     * @param field
     * @param operator
     * @param value1
     * @param value2
     * @return
     */
    public QueryContext and(final String field, NOT_BETWEEN operator, final Object value1, final Object value2) {
        this.add(QueryContextPiece.and(field, operator, value1, value2));
        return this;
    }

    /**
     * 等于
     * 
     * @param field
     * @param operator
     * @param value
     * @return
     */
    public QueryContext or(final String field, EQ operator, final Object value) {
        this.add(QueryContextPiece.or(field, operator, value));
        return this;
    }

    /**
     * 不等于
     * 
     * @param field
     * @param operator
     * @param value
     * @return
     */
    public QueryContext or(final String field, NOT_EQ operator, final Object value) {
        this.add(QueryContextPiece.or(field, operator, value));
        return this;
    }

    /**
     * 小于
     * 
     * @param field
     * @param operator
     * @param value
     * @return
     */
    public QueryContext or(final String field, LT operator, final Object value) {
        this.add(QueryContextPiece.or(field, operator, value));
        return this;
    }

    /**
     * 大于
     * 
     * @param field
     * @param operator
     * @param value
     * @return
     */
    public QueryContext or(final String field, GT operator, final Object value) {
        this.add(QueryContextPiece.or(field, operator, value));
        return this;
    }

    /**
     * 小于等于
     * 
     * @param field
     * @param operator
     * @param value
     * @return
     */
    public QueryContext or(final String field, LE operator, final Object value) {
        this.add(QueryContextPiece.or(field, operator, value));
        return this;
    }

    /**
     * 大于等于
     * 
     * @param field
     * @param operator
     * @param value
     * @return
     */
    public QueryContext or(final String field, GE operator, final Object value) {
        this.add(QueryContextPiece.or(field, operator, value));
        return this;
    }

    /**
     * 是否空
     * 
     * @param field
     * @param operator
     * @return
     */
    public QueryContext or(final String field, NULL operator) {
        this.add(QueryContextPiece.or(field, operator));
        return this;
    }

    /**
     * 是否非空
     * 
     * @param field
     * @param operator
     * @return
     */
    public QueryContext or(final String field, NOT_NULL operator) {
        this.add(QueryContextPiece.or(field, operator));
        return this;
    }

    /**
     * 模糊匹配
     * 
     * @param field
     * @param operator
     * @param value
     * @return
     */
    public QueryContext or(final String field, LIKE operator, final Object value) {
        this.add(QueryContextPiece.or(field, operator, value));
        return this;
    }

    /**
     * 包含
     * 
     * @param field
     * @param operator
     * @param value
     * @return
     */
    @SuppressWarnings("unchecked")
    public <Z extends Object> QueryContext or(final String field, IN operator, final Z... value) {
        this.add(QueryContextPiece.or(field, operator, value));
        return this;
    }

    /**
     * 不包含
     * 
     * @param field
     * @param operator
     * @param value
     * @return
     */
    @SuppressWarnings("unchecked")
    public <Z extends Object> QueryContext or(final String field, NOT_IN operator, final Z... value) {
        this.add(QueryContextPiece.or(field, operator, value));
        return this;
    }

    /**
     * 两者之间
     * 
     * @param field
     * @param operator
     * @param value1
     * @param value2
     * @return
     */
    public QueryContext or(final String field, BETWEEN operator, final Object value1, final Object value2) {
        this.add(QueryContextPiece.or(field, operator, value1, value2));
        return this;
    }

    /**
     * 两者之外
     * 
     * @param field
     * @param operator
     * @param value1
     * @param value2
     * @return
     */
    public QueryContext or(final String field, NOT_BETWEEN operator, final Object value1, final Object value2) {
        this.add(QueryContextPiece.or(field, operator, value1, value2));
        return this;
    }

    @Override
    public Iterator<QueryContextPiece> iterator() {
        return this.pieces.iterator();
    }

}
